Fork me on GitHub

《流畅的Python》读书笔记----第一章 Python数据模型

[toc]

第一章 Python数据模型

一摞Python风格的纸牌

1
2
3
4
5
6
7
8
9
10
11
12
import collections
Card = collections.namedtuple('Card',['rank','suit'])
class FrenchDeck:
ranks = [str(n) for n in range(2,11)] + list("JQKA")
suits = 'spades diamonds clubs hearts'.split()
def __init__(self):
self.__cards = [Card(rank,suit) for suit in self.suits
for rank in self.ranks]
def __len__(self):
return len(self.__cards)
def __getitem__(self,position):
return self.__cards[position]

由FrenchDeck类生成的对象,可以使用len()按下标取值

1
2
3
4
5
>>> deck = FrenchDeck()
>>> len(deck)
52
>>>deck[0]
Card(rank='2',suit='spades')

当使用len()时,Python的解释器会自动的调用FrenchDeck类中的__len__方法,对deck对象用下标取值时,自动调用__getitem__方法。

如何使用特殊方法

特殊方法是给Python解释器调用的,我们自己并不需要调用他们。

模拟数值类型

下例是一个Vector类(向量,模拟向量的加法数乘等运算)的实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from math import hypot
# hypot() 返回欧几里德范数 sqrt(x*x + y*y)
class Vector:

def __init__(self,x=0,y=0):
self.x = x
self.y = y
# repr 的作用是把一个对象用字符串的形式表达出来
def __repr__(self):
return 'Vector(%r,%r)' % (self.x,self.y)
# 向量的绝对值
def __abs__(self):
return hypot(self.x,self.y)

def __bool__(self):
return bool(abs(self))

def __add__(self,other):
x = self.x + other.x
y = self.y + other.y
return Vector(x,y)

def __mul__(self,scalar):
return Vector(self.x*scalar,self.y*scalar)

为什么len不是普通方法

如果x是一个内置类型,那么,CPython会直接从一个C结构体里读取对象的长度,完全不用调用任何方法,速度很快。也可以把len用于我们自定义的类型。